import {
  Component,
  Host,
  h,
  Element,
  Prop,
  ComponentInterface,
  State,
  Watch,
  Event,
  EventEmitter,
  writeTask,
} from '@stencil/core';
import interact from 'interactjs';

/**
 * 分割面板
 *
 * @export
 * @class IBzSplit
 * @implements {ComponentInterface}
 */
@Component({
  tag: 'ibz-split',
  styleUrl: 'ibz-split.scss',
  shadow: true,
})
export class IBzSplit implements ComponentInterface {
  /**
   * 当前组件
   *
   * @type {HTMLIbzSplitElement}
   * @memberof IBzSplit
   */
  @Element()
  el: HTMLIbzSplitElement;

  /**
   * 分割线DOM实例
   *
   * @type {HTMLDivElement}
   * @memberof IBzSplit
   */
  line: HTMLDivElement;

  /**
   * horizontal: 左右分割，vertical: 上下分割
   *
   * @type {('horizontal' | 'vertical')}
   * @memberof IBzSplit
   */
  @Prop()
  mode: 'horizontal' | 'vertical' = 'horizontal';

  /**
   * 保险数值
   *
   * @memberof IBzSplit
   */
  @Prop()
  insuranceNum = 50;

  /**
   * 分割比例，小于1按照比例算。大于等于1按照px算
   *
   * @memberof IBzSplit
   */
  @Prop()
  split = 0.3;
  @Watch('split')
  splitWatch(): void {
    this.calcDefaultNum();
  }

  /**
   * 当split大于1时，是否反转默认值
   *
   * @author chitanda
   * @date 2021-06-22 11:06:11
   */
  @Prop()
  splitReverse = false;

  /**
   * 分割宽度参数
   *
   * @memberof IBzSplit
   */
  @State()
  num = 100;

  /**
   * 是否正在拖拽中
   *
   * @author chitanda
   * @date 2021-06-22 11:06:29
   */
  @State()
  isDrag = false;

  /**
   * 是否为上下布局
   *
   * @memberof IBzSplit
   */
  isVertical = false;

  /**
   * 鼠标显示符号
   *
   * @memberof IBzSplit
   */
  mouseCursor = 'e-resize';

  /**
   * 分割值变更事件
   *
   * @type {EventEmitter<number>}
   * @memberof IBzSplitPanel
   */
  @Event({ eventName: 'split-change' })
  splitChange: EventEmitter<number>;

  /**
   * 计算默认宽或高
   *
   * @memberof IBzSplit
   */
  calcDefaultNum(): void {
    if (isNaN(this.split)) {
      this.split = 0.3;
    }
    if (this.split >= 1) {
      if (this.isVertical) {
        this.num = this.el.offsetHeight - this.split;
      } else {
        if (this.splitReverse) {
          this.num = this.el.offsetWidth - this.split;
        } else {
          this.num = this.split;
        }
      }
    } else {
      if (this.isVertical) {
        this.num = this.el.offsetHeight - this.el.offsetHeight * this.split;
      } else {
        this.num = this.el.offsetWidth * this.split;
      }
    }
  }

  componentDidLoad() {
    // 计算方向
    this.isVertical = this.mode === 'vertical';
    writeTask(() => {
      this.calcDefaultNum();
    });
    // 计算展示值
    this.mouseCursor = !this.isVertical ? 'e-resize' : 'row-resize';
    const axis = !this.isVertical ? 'x' : 'y';
    interact(this.line).draggable({
      // 锁定起始轴
      startAxis: axis,
      // 锁定可拖拽轴
      lockAxis: axis,
      // 设置拖拽生效区域
      modifiers: [
        // 保持在父对象内部
        interact.modifiers.restrictEdges({ outer: this.el }),
      ],
      cursorChecker: () => {
        return this.mouseCursor;
      },
      onstart: () => {
        this.isDrag = true;
      },
      onend: () => {
        this.isDrag = false;
      },
      onmove: (e: any) => {
        this.splitMove(e);
      },
    });
  }

  splitMove(e: any) {
    if (this.isVertical) {
      const newNum = this.num + e.delta.y;
      if (newNum < this.insuranceNum) {
        return;
      }
      if (newNum > this.el.offsetHeight - this.insuranceNum) {
        return;
      }
      this.num = newNum;
    } else {
      const newNum = this.num + e.delta.x;
      if (newNum < this.insuranceNum) {
        return;
      }
      if (newNum > this.el.offsetWidth - this.insuranceNum) {
        return;
      }
      this.num = newNum;
    }
  }

  render() {
    const style: any = {};
    const lineStyle: any = {};
    if (this.isVertical) {
      style.height = this.num + 'px';
      lineStyle.top = style.height;
    } else {
      style.width = this.num + 'px';
      lineStyle.left = style.width;
    }
    return (
      <Host>
        <div class={{ 'ibz-split-panel-wrapper': true, horizontal: !this.isVertical, vertical: this.isVertical }}>
          <div
            class={{
              'ibz-split-panel': true,
              left: !this.isVertical,
              top: this.isVertical,
            }}
            style={style}
          >
            <div class='ibz-split-mask' style={{ display: this.isDrag ? 'block' : 'none' }}></div>
            <slot />
          </div>
          <div ref={ref => (this.line = ref)} class='dividing-line' style={lineStyle} />
          <div
            class={{
              'ibz-split-panel': true,
              right: !this.isVertical,
              bottom: this.isVertical,
            }}
          >
            <div class='ibz-split-mask' style={{ display: this.isDrag ? 'block' : 'none' }}></div>
            <slot name='content' />
          </div>
        </div>
      </Host>
    );
  }
}
